/******************************************************************************* 
  Copyright (C), 2018-2050, auditoryworks Tech. Co., Ltd.
  Description:   MEDIA ALG模块  
  Function List:     
  History:
    <wangmc -- 2019-12-02>  创建
*******************************************************************************/ 

/*=============================================================================
                                 Includes                                  
 =============================================================================*/
#include "mediaPriv.h"
/*=============================================================================
                               Macro Definition
 =============================================================================*/

/*=============================================================================
                        Local Structures and Typedef 
 =============================================================================*/

/*=============================================================================
                             Extern Variables                                  
=============================================================================*/

/*=============================================================================
                             Local Variables                                  
 =============================================================================*/

/*=============================================================================
                             Function Definition                                  
 =============================================================================*/
int MEDIA_CommonGetZoomAbs(void)
{
    return mediaCtl_g.cfg.zoomAbs;
}

int MEDIA_CommonGetPanAbs(void)
{
    return mediaCtl_g.cfg.panAbs;
}

int MEDIA_CommonGetTiltAbs(void)
{
    return mediaCtl_g.cfg.tiltAbs;
}

int MEDIA_CommonGetMirror(void)
{    
    return mediaCtl_g.cfg.inOptions.mirror;
}

int MEDIA_CommonGetFlip(void)
{    
    return mediaCtl_g.cfg.inOptions.flip;
}

static int MEDIA_CommonSetOptions(VideoInOptions *pOptions)
{
    int status;
    VideoInput *pVideoInput;

    pVideoInput = mediaCtl_g.pVideoInput;
    if (!pVideoInput)
    {
        LOG_PrintError("pVideoInput is NULL!\n");
        return -1;
    }

    status = pVideoInput->setOptions(pVideoInput, pOptions);
    if (status)
    {
        LOG_PrintError("Fail to get options.\n");
        return -1;
    }
    
    return 0;
}

int MEDIA_CommonEnableMirror(int enable)
{
    int ret;
    char key[8] = {0};
    VideoInOptions options;

    memcpy(&options, &mediaCtl_g.cfg.inOptions, sizeof(VideoInOptions));

    options.mirror = enable;

    ret = MEDIA_CommonSetOptions(&options);
    if (ret)
    {
        return -1;
    }

    mediaCtl_g.cfg.inOptions.mirror = options.mirror;

    sprintf(key, "%d", options.mirror);
    ret = INI_KeySet(CONFIG_PATH, "videoView", "mirror", key);
    if (ret)
    {
        return -1;
    }

    return 0;
}

int MEDIA_CommonEnableFlip(int enable)
{
    int ret;
    char key[8] = {0};
    VideoInOptions options;

    memcpy(&options, &mediaCtl_g.cfg.inOptions, sizeof(VideoInOptions));

    options.flip = enable;

    ret = MEDIA_CommonSetOptions(&options);
    if (ret)
    {
        return -1;
    }

    mediaCtl_g.cfg.inOptions.flip = options.flip;

    sprintf(key, "%d", options.flip);
    ret = INI_KeySet(CONFIG_PATH, "videoView", "flip", key);
    if (ret)
    {
        return -1;
    }

    return 0;
}


static int MEDIA_CommonCalcCropRect(int zoomAbs, int pan, int tilt, Rect_ext *pRect)
{
    int uintSteps;

    uintSteps = 8;//(mediaCtl_g.viWidth - 960)/360;
#if 0
    pRect->w = ALIGN_DOWN((VI_WIDTH - (zoomAbs - 40)*uintSteps), 2);
    pRect->h = ALIGN_DOWN((pRect->w*VI_HEIGHT)/VI_WIDTH, 2);
    //pRect->w = ALIGN_DOWN((640*240)/zoomAbs, 2);
    //pRect->h = ALIGN_DOWN((360*240)/zoomAbs, 2);
    pRect->x = (VI_WIDTH - pRect->w)/2;
    pRect->y = (VI_HEIGHT - pRect->h)/2;
#else
    pRect->w = mediaCtl_g.viWidth - (zoomAbs - 40)*uintSteps;
    pRect->h = (pRect->w*mediaCtl_g.viHeight)/mediaCtl_g.viWidth;
    pRect->x = (mediaCtl_g.viWidth - pRect->w)/2;
    pRect->y = (mediaCtl_g.viHeight - pRect->h)/2;
#endif

    pRect->x += (pan*mediaCtl_g.viWidth)/120;
    pRect->y -= (tilt*mediaCtl_g.viHeight)/90;

    if (pRect->x < 0)
    {
        pRect->x = 0;
    }

    if (pRect->y < 0)
    {
        pRect->y = 0;
    }

    if ((pRect->w+pRect->x) > mediaCtl_g.viWidth)
    {
        pRect->x = mediaCtl_g.viWidth - pRect->w;
    }

    if ((pRect->h+pRect->y) > mediaCtl_g.viHeight)
    {
        pRect->y = mediaCtl_g.viHeight - pRect->h;
    }
    
    return 0;
}

int MEDIA_CommonSetPreset(int index)
{
    VideoEncoder *pVideoEncoder;

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];

    /* 没有设置预置点 */
    if (-1 == mediaCtl_g.cfg.preset[index].zoomAbs)
    {
        return -1;
    }

    if ((mediaCtl_g.cfg.aiMode != 0) || (mediaCtl_g.cfg.speakTrackMode == 2))
    {
        pthread_mutex_lock(&mediaCtl_g.algMutex);
        pVideoEncoder->setScreenMode(pVideoEncoder, 0);
        mediaCtl_g.cfg.speakTrackMode = 0;
        mediaCtl_g.cfg.aiMode = 0;
        pthread_mutex_unlock(&mediaCtl_g.algMutex);
    }
    
    mediaCtl_g.cfg.zoomAbs = mediaCtl_g.cfg.preset[index].zoomAbs;
    mediaCtl_g.cfg.panAbs = mediaCtl_g.cfg.preset[index].panAbs;
    mediaCtl_g.cfg.tiltAbs = mediaCtl_g.cfg.preset[index].tiltAbs;
    
    return 0;
}

int MEDIA_CommonSavePreset(int index)
{
    int ret;
    char sec[32] = {0};
    char key[8] = {0};

    sprintf(sec, "preset.%d", index);
    sprintf(key, "%d", mediaCtl_g.cfg.zoomAbs);
    ret = INI_KeySet(CONFIG_PATH, sec, "zoom", key);
    if (ret)
    {
        return -1;
    }

    sprintf(key, "%d", mediaCtl_g.cfg.panAbs);
    ret = INI_KeySet(CONFIG_PATH, sec, "pan", key);
    if (ret)
    {
        return -1;
    }

    sprintf(key, "%d", mediaCtl_g.cfg.tiltAbs);
    ret = INI_KeySet(CONFIG_PATH, sec, "tilt", key);
    if (ret)
    {
        return -1;
    }
    
    mediaCtl_g.cfg.preset[index].zoomAbs = mediaCtl_g.cfg.zoomAbs;
    mediaCtl_g.cfg.preset[index].panAbs = mediaCtl_g.cfg.panAbs;
    mediaCtl_g.cfg.preset[index].tiltAbs = mediaCtl_g.cfg.tiltAbs;

    return 0;
}

void MEDIA_CommonSetZoomAbs(short val)
{
    VideoEncoder *pVideoEncoder;
    VideoEncCropCfg encCropCfg;
    
    encCropCfg.enable = 1;

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];

    if ((mediaCtl_g.cfg.aiMode != 0) || (mediaCtl_g.cfg.speakTrackMode == 2))
    {
        pthread_mutex_lock(&mediaCtl_g.algMutex);
        pVideoEncoder->setScreenMode(pVideoEncoder, 0);
        mediaCtl_g.cfg.speakTrackMode = 0;
        mediaCtl_g.cfg.aiMode = 0;
        pthread_mutex_unlock(&mediaCtl_g.algMutex);
    }
    
    mediaCtl_g.cfg.zoomAbs = val;

    MEDIA_CommonCalcCropRect(val, 0, 0, &encCropCfg.rect);
            
    pVideoEncoder->setEncodeCrop(pVideoEncoder, &encCropCfg);
    
    return ;
}

void MEDIA_CommonSetOriginal(void)
{
    VideoEncoder *pVideoEncoder;

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];

    if ((mediaCtl_g.cfg.aiMode != 0) || (mediaCtl_g.cfg.speakTrackMode == 2))
    {
        pthread_mutex_lock(&mediaCtl_g.algMutex);
        pVideoEncoder->setScreenMode(pVideoEncoder, 0);
        mediaCtl_g.cfg.speakTrackMode = 0;
        mediaCtl_g.cfg.aiMode = 0;
        pthread_mutex_unlock(&mediaCtl_g.algMutex);
    }
    
    return ;
}

void MEDIA_CommonRecoverSet(void)
{
    int ret = 0;
    int val = 0;
    int screenMode;
    MEDIA_cfg_t *pCfg;
    VideoEncoder *pVideoEncoder;

    pCfg = &mediaCtl_g.cfg;
    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];

    pthread_mutex_lock(&mediaCtl_g.algMutex);

    ret |= INI_KeyGetInt(CONFIG_PATH, "alg", "aimode", &val);
    pCfg->aiMode = val;
    ret |= INI_KeyGetInt(CONFIG_PATH, "alg", "speakertrack", &val);
    pCfg->speakTrackMode = val;
    
    if (0 == pCfg->aiMode)
    {
        screenMode = 0;
    }
    else
    {
        if (pCfg->speakTrackMode == 2)
        {
            screenMode = 1;
        }
        else
        {
            screenMode = 0;
        }
    }

    pVideoEncoder->setScreenMode(pVideoEncoder, screenMode);

    pthread_mutex_unlock(&mediaCtl_g.algMutex);
    
    return ;
}

void MEDIA_CommonSetPanAbs(int val)
{
    VideoEncoder *pVideoEncoder;

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];

    if ((mediaCtl_g.cfg.aiMode != 0) || (mediaCtl_g.cfg.speakTrackMode == 2))
    {
        pthread_mutex_lock(&mediaCtl_g.algMutex);
        pVideoEncoder->setScreenMode(pVideoEncoder, 0);
        mediaCtl_g.cfg.speakTrackMode = 0;
        mediaCtl_g.cfg.aiMode = 0;
        pthread_mutex_unlock(&mediaCtl_g.algMutex);
    }
    
    mediaCtl_g.cfg.panAbs = val;
    
    return ;
}

void MEDIA_CommonSetTiltAbs(int val)
{
    VideoEncoder *pVideoEncoder;

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];

    if ((mediaCtl_g.cfg.aiMode != 0) || (mediaCtl_g.cfg.speakTrackMode == 2))
    {
        pthread_mutex_lock(&mediaCtl_g.algMutex);
        pVideoEncoder->setScreenMode(pVideoEncoder, 0);
        mediaCtl_g.cfg.speakTrackMode = 0;
        mediaCtl_g.cfg.aiMode = 0;
        pthread_mutex_unlock(&mediaCtl_g.algMutex);
    }
    
    mediaCtl_g.cfg.tiltAbs = val;
    
    return ;
}

void MEDIA_CommonSetVideoCover(int enable)
{
    static int oldAiMode = -1;
    VideoCover cover;
    VideoEncoder *pVideoEncoder;

    memset(&cover, 0, sizeof(cover));

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];

    if (enable)
    {
        pthread_mutex_lock(&mediaCtl_g.algMutex);
        oldAiMode = mediaCtl_g.cfg.aiMode;
        mediaCtl_g.cfg.aiMode = 0;
        pthread_mutex_unlock(&mediaCtl_g.algMutex);
    }
    else
    {
        pthread_mutex_lock(&mediaCtl_g.algMutex);
        if (oldAiMode != -1)
        {
            mediaCtl_g.cfg.aiMode = oldAiMode;
        }
        pthread_mutex_unlock(&mediaCtl_g.algMutex);
    }

    cover.enable = enable;
    pVideoEncoder->setCover(pVideoEncoder, &cover);
    
    return ;
}

int MEDIA_CommonSetTitle(VideoTitle *pTitle)
{
    VideoEncoder *pVideoEncoder;

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];

    pVideoEncoder->setTitle(pVideoEncoder, pTitle);

    return 0;
}

int MEDIA_CommonEnableAi(int enable)
{
    int ret;
    char key[8] = {0};
    int screenMode;
    VideoEncoder *pVideoEncoder;

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];
    
    sprintf(key, "%d", enable);
    ret = INI_KeySet(CONFIG_PATH, "alg", "aimode", key);
    if (ret)
    {
        return -1;
    }

    pthread_mutex_lock(&mediaCtl_g.algMutex);

    mediaCtl_g.cfg.aiMode = enable;
    
    if (0 == enable)
    {
        screenMode = 0;
    }
    else
    {
        if (mediaCtl_g.cfg.speakTrackMode == 2)
        {
            screenMode = 1;
        }
        else
        {
            screenMode = 0;
        }
    }

    pVideoEncoder->setScreenMode(pVideoEncoder, screenMode);

    pthread_mutex_unlock(&mediaCtl_g.algMutex);
    
    return 0;
}

int MEDIA_CommonGetAi(void)
{    
    return mediaCtl_g.cfg.aiMode;
}


int MEDIA_CommonGetOsdMirror(void)
{    
    return mediaCtl_g.cfg.osdMirror;
}

int MEDIA_CommonSetOsdMirror(int enable)
{    
    int ret;
    char key[8] = {0};
    
    sprintf(key, "%d", enable);
    ret = INI_KeySet(CONFIG_PATH, "osd", "mirror", key);
    if (ret)
    {
        return -1;
    }

    mediaCtl_g.cfg.osdMirror = enable;

    return 0;
}

int MEDIA_CommonSetSpeakerTrack(int mode)
{
    int ret;
    char key[8] = {0};
    int screenMode;
    VideoEncCropCfg encCropCfg;
    VideoEncoder *pVideoEncoder;

    pVideoEncoder = mediaCtl_g.pVideoEncoder[USBTYPEC_OUT];
    
    sprintf(key, "%d", mode);
    ret = INI_KeySet(CONFIG_PATH, "alg", "speakertrack", key);
    if (ret)
    {
        return -1;
    }

    pthread_mutex_lock(&mediaCtl_g.algMutex);

    mediaCtl_g.cfg.speakTrackMode = mode;

    if (2 == mode)
    {
        encCropCfg.enable = 0;
        encCropCfg.rect.x = 0;
        encCropCfg.rect.y = 0;
        encCropCfg.rect.w = VI_WIDTH;
        encCropCfg.rect.h = VI_HEIGHT;
        pVideoEncoder->setEncodeCrop(pVideoEncoder, &encCropCfg);
            
        screenMode = 1;
    }
    else
    {
        screenMode = 0;
    }
    pVideoEncoder->setScreenMode(pVideoEncoder, screenMode);

    pthread_mutex_unlock(&mediaCtl_g.algMutex);
    
    return 0;
}

int MEDIA_CommonGetSpeakerTrack(void)
{    
    return mediaCtl_g.cfg.speakTrackMode;
}

int MEDIA_CommonGetZoomTime(void)
{    
    return mediaCtl_g.cfg.zoomTimes;
}

int MEDIA_CommonSetZoomTime(int times)
{
    int ret;
    char key[8] = {0};

    mediaCtl_g.cfg.zoomTimes = times;

    sprintf(key, "%d", mediaCtl_g.cfg.zoomTimes);
    ret = INI_KeySet(CONFIG_PATH, "alg", "tracktime", key);
    if (ret)
    {
        return -1;
    }

    return 0;
}

int MEDIA_CommonGetSplitCnt(void)
{    
    return mediaCtl_g.cfg.maxSplitCnt;
}

int MEDIA_CommonSetSplitCnt(int cnt)
{
    int ret;
    char key[8] = {0};

    mediaCtl_g.cfg.maxSplitCnt = cnt;

    sprintf(key, "%d", mediaCtl_g.cfg.maxSplitCnt);
    ret = INI_KeySet(CONFIG_PATH, "alg", "splitcnt", key);
    if (ret)
    {
        return -1;
    }

    return 0;
}

int MEDIA_CommonEnablePrivacy(int enable)
{
    int ret;
    char key[8] = {0};
    
    mediaCtl_g.cfg.privacy = enable;
    
    sprintf(key, "%d", enable);
    ret = INI_KeySet(CONFIG_PATH, "privacy", "enable", key);
    if (ret)
    {
        return -1;
    }
    
    return 0;
}

int MEDIA_CommonGetPrivacy(void)
{    
    return mediaCtl_g.cfg.privacy;
}

int MEDIA_CommonSetLineFreq(unsigned char value)
{
    int ret;
    char key[8] = {0};
    VideoInOptions options;

    memcpy(&options, &mediaCtl_g.cfg.inOptions, sizeof(VideoInOptions));

    options.antiFlicker = value;

    ret = MEDIA_CommonSetOptions(&options);
    if (ret)
    {
        return -1;
    }

    mediaCtl_g.cfg.inOptions.antiFlicker = options.antiFlicker;

    sprintf(key, "%d", options.antiFlicker);
    ret = INI_KeySet(CUSTOM_PATH, "custom", "exposure_frequency", key);
    if (ret)
    {
        return -1;
    }

    return 0;
}

unsigned char MEDIA_CommonGetLineFreq(void)
{
    return mediaCtl_g.cfg.inOptions.antiFlicker;
}

static void *MEDIA_CommonCropThd(void *parg)
{
    MEDIA_cfg_t *pCfg = (MEDIA_cfg_t *)parg;
    int zoomAbs = 40;
    int panAbs = 0;
    int tiltAbs = 0;
    VideoEncCropCfg encCropCfg;
    
    prctl(PR_SET_NAME, __func__);
    LOG_PrintInfo("tid:%d\n", gettid());
    
    encCropCfg.enable = 1;
     
    while (1)
    {
        if ((zoomAbs != pCfg->zoomAbs) 
            || (panAbs != pCfg->panAbs)
            || (tiltAbs != pCfg->tiltAbs))
        {
            zoomAbs = pCfg->zoomAbs; 
            panAbs = pCfg->panAbs;
            tiltAbs = pCfg->tiltAbs;

            MEDIA_CommonCalcCropRect(zoomAbs, panAbs/3600, tiltAbs/3600, &encCropCfg.rect);
            
            mediaCtl_g.pVideoEncoder[USBTYPEC_OUT]->setEncodeCrop(mediaCtl_g.pVideoEncoder[USBTYPEC_OUT], &encCropCfg);
        }
        usleep(10*1000);
    }

    return NULL;
}

int MEDIA_CommonInit(void)
{
    int ret;
    pthread_t cropThd;

    ret = pthread_create(&cropThd, 0, MEDIA_CommonCropThd, &mediaCtl_g.cfg);
    if (ret)
    {
        LOG_PrintError("can't create thread: %s\n", strerror(ret));
        return -1;
    }

    return 0;
}

